import ika
import engine
import controls
import entity

class Camera(object):
    def __init__(self):
        self.x = 0
        self.y = 0
        self.entity = None
        
    def MoveTo(self, x, y):
        self.x = x
        self.y = y
        
    def FollowEntity(self, entity):
        self.entity = entity

    def Update(self):
        if self.entity:
            self.x = self.entity.x - (ika.Video.xres / 2.0)
            self.y = self.entity.y - (ika.Video.yres / 2.0)
    
        if self.x < 0:
            self.x = 0.0
        elif self.x + ika.Video.xres > ika.Map.width:
            self.x = ika.Map.width - ika.Video.xres
        if self.y < 0:
            self.y = 0.0
        elif self.y + ika.Video.yres > ika.Map.height:
            self.y = ika.Map.height - ika.Video.yres

        ika.Map.xwin = int(self.x)
        ika.Map.ywin = int(self.y)

class Zone(object):
    def __init__(self, x, y, width, height, event):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.event = event
        
    def Activate(self, entity):
        eventInfo = event.EventInfo(self, entity)
        if self.event in dir(ika.Map.module):
            eval("ika.Map.module." + self.event + "(eventInfo)")

class Layer(object):
    def __init__(self, layer_index):
        self.layer_index = layer_index
        self.zones = []
        self.name, self.width, self.height, self.wrapx, self.wrapy = ika.Map.GetLayerProperties(layer_index)
        for zone_x, zone_y, zone_width, zone_height, zone_event in ika.Map.GetZones(layer_index):
            self.zones.append(Zone(zone_x, zone_y, zone_width, zone_height, zone_event))

def EntityRenderSort(ls, rs):
    if ls.z_index != rs.z_index:
        return int(ls.z_index - rs.z_index)
    else:
        return int(ls.y - rs.y)

class MapEngine(object):
    def __init__(self):
        self.filename = ""
        self.entities = []
        self.layers = []
        self.camera = Camera()
        self.player = None

    def SwitchMap(self, filename):
        self.entities = []
        self.player = None
        self.filename = filename
        if self.Render not in engine.render_list:
            engine.render_list.insert(0, self.Render)
        if self.Input not in engine.input_list:
            engine.input_list.insert(0, self.Input)
        if self.Update not in engine.update_list:
            engine.update_list.insert(0, self.Update)
            
        ika.SetCameraTarget(None)
        ika.Map.Switch(self.filename)
            
        self.layers = []
        for i in range(ika.Map.layercount):
            self.layers.append(Layer(i))
        
        self.camera.MoveTo(ika.Map.xwin, ika.Map.ywin)

    def SetPlayer(self, entity):
        self.player = entity
        self.FollowPlayer()
        if entity not in self.entities:
            self.entities.append(entity)
            print entity
    
    def FollowPlayer(self):
        self.camera.FollowEntity(self.player)
        
    def FreezeCamera(self):
        self.camera.FollowEntity(None)          

    def Render(self):
        for layer in self.layers:
            ika.Render(layer.layer_index)
            [e.Draw(self.camera.x, self.camera.y) for e in sorted(self.entities, EntityRenderSort) if (e.layer == layer.layer_index and e.visible)]
    
    def Update(self):
        self.camera.Update()
        for entity in self.entities:
            entity.Update()
            
    def Input(self, held, pressed):
        if self.player == None:
            if "left" in held:
                self.camera.x -= 1
            if "right" in held:
                self.camera.x += 1
            if "up" in held:
                self.camera.y -= 1
            if "down" in held:
                self.camera.y += 1
        else:
            self.player.Input(held, pressed)
        
    def GetObsPixel(self, x, y, layer):
        if (x < 0
            or x > ika.Map.width 
            or y < 0
            or y > ika.Map.height):
                return True
        return bool(ika.Map.GetObs(x / 16, y / 16, layer))
        
    def GetEntityObsPixel(self, entity_self, x, y, layer):
        if not entity_self.obstructed_by_entities:
            return False
        for entity in self.entities:
            if entity == entity_self or not entity.is_obstruction:
                continue
            if (x >= entity.x
                    and x <= entity.x + entity.hotspot_width
                    and y >= entity.y
                    and y <= entity.y + entity.hotspot_height):
                return True
        return False
        
    def GetZone(self, x, y, width, height, layer):
        for zone in self.layers[layer].zones:
            if (x + width >= zone.x
                and x <= zone.x + zone.width
                and y + height >= zone.y
                and y <= zone.y + zone.height):
                    return zone
        return None
     
    def GetEntitiesInRectangle(self, entity_self, x, y, x2, y2):
        results = []
        for entity in self.entities:
            if entity != entity_self and entity.CollidesWith(x, y, x2, y2):
                results.append(entity)
        return results
        
map_engine = MapEngine()